#ifndef INDICEBOOLEANO_H_
#define INDICEBOOLEANO_H_

#include <string>
#include <vector>
#include <fstream>
#include "../BTree/BTree.h"
#include "../ArchFrase/ArchFrases.h"
#include "../utils/BTree/TreePrinter.h"
#include "ListaInvertida/ArchListaInvertida.h"
#include "ListaInvertida/BloqueListaInvertida.h"


/** El indice booleano esta compuesto de un archivo con todos los terminos en los
 * documentos, este archivo ademas contiene referencias a otro archivo con las listas invertidas
 * de los ID de los documentos que contienen a esos terminos
 * */
class IndiceBooleano {
	private:
		BTree terminos;
		ArchListaInvertida listaInvertida;

		// Devuelve un vector con los terminos de la frase
		std::vector<std::string> procesarTerminosFrase(std::string frase, BTree& terminos) const;

		// Almacena el termino en el arbol si este no existe, devuelve el ID del termino
		unsigned int almacenarTermino(std::string termino);
		void almacenarTerminoSinID(std::string termino);

		// Almacena el par en un archivo de ocurrencias de terminos
		/*
		void almacenarOcurrenciaTermino(unsigned int docID, unsigned int  termID, std::fstream &arch) const;
		void almacenarOcurrenciaTermino(unsigned int docID, std::string termino, std::fstream &arch) const;
		*/

		// Construye el archivo de ocurrencias de terminos y devuelve su nombre
		std::string construirArchOcurrenciasTerminos(ArchFrases& frases, BTree& terminosValidos);
		void construirListasInvertidas(std::string nomOcurrenciasOrdenado);

		// Guarda la lista invertida en el archivo y devuelve su nro de bloque
		unsigned int AlmacenarListaInvertida(std::vector<unsigned int>& lDocsID);

		// Actualiza el termino agregandole una referencia al bloque con la lista invertida de documentos
		void updateTermino(std::string termino, unsigned int nroBloque);

		// Realiza la interseccion de las listas de id de documentos
		std::vector<unsigned int> intersectarListasInvertidas(std::vector<BloqueListaInvertida> &vecListas);
		void normalizarIDs(std::vector<unsigned int> &vecIDs) const;

		// Nada de copias o asignaciones
		IndiceBooleano(const IndiceBooleano&) { }

	public:
		IndiceBooleano();
		virtual ~IndiceBooleano();

		// Dadas las frases y los terminos (sin stop-words) crea el indice booleano
		bool crearIndices(ArchFrases& frases, BTree& terminosValidos,
				std::string nomArchTerminos = "idxTerm.bin", std::string nomArchListas = "idxListInv.bin");

		// Por si ya existen los archivos, se pueden abrir
		bool abrirIndices(std::string nomArchTerminos = "idxTerm.bin", std::string nomArchListas = "idxListInv.bin");
		void cerrar();

		// Dada una lista de terminos devuelve una lista de "ID" de documentos
		std::vector<unsigned int> buscarDocumentos(std::vector<std::string> &lTerminos);

		void altaDocumento(std::string frase, unsigned int docID, BTree& terminosValidos);
		void bajaDocumento(std::string frase, unsigned int docID, BTree& terminosValidos);
};

#endif /* INDICEBOOLEANO_H_ */
